#pragma once
/*
 * msgpack codec with msgpack-c.
 */
#include "msgpack-c/msgpack.hpp"

namespace anet {
	namespace rpc_codec {
		using buffer_type = msgpack::sbuffer;
		struct msgpack_codec {
			const static size_t gMsgPackInitSize = 2 * 1024;

			template <typename... Args> 
			static buffer_type pack_args(Args&&...args) {
				buffer_type buffer(gMsgPackInitSize);
				msgpack::pack(buffer, std::forward_as_tuple(std::forward<Args>(args)...));
				return buffer;
			}

			template <typename Arg, typename... Args,
				typename = typename std::enable_if<std::is_enum<Arg>::value>::type>
				static std::string pack_args_str(Arg arg, Args&&...args) {
				buffer_type buffer(gMsgPackInitSize);
				msgpack::pack(buffer, std::forward_as_tuple((int)arg, std::forward<Args>(args)...));
				return std::string(buffer.data(), buffer.size());
			}

			template <typename T> 
			buffer_type pack(T&& t) const {
				buffer_type buffer;
				msgpack::pack(buffer, std::forward<T>(t));
				return buffer;
			}

			template <typename T> 
			T unpack(char const* data, size_t length) {
				try {
					msgpack::unpack(m_msg, data, length);
					return m_msg.get().as<T>();
				} catch (...) {
					throw std::invalid_argument("unpack failed: Args not match!");
				}
			}

		private:
			msgpack::unpacked m_msg;
		};
	}
} 